
#include "DefinitionFonction.h"
#include "Identifiant.h"
#include "InstructionBase.h"
#include "Expression.h"

//Constructeur

DefinitionFonction::DefinitionFonction(){

}

//Destruction des variable alloué dynamiquement dans le destructeur de la classe.

DefinitionFonction::~DefinitionFonction(){
	delete m_identifiant;
	delete m_expression;

	for(int i = 0; i < m_identifiants.size() ; i++){
		delete m_identifiants.at(i);
	}

	for(int i = 0; i < m_instructionBases.size() ; i++){
		delete m_instructionBases.at(i);
	}

}

// Permet d'ajouter le code Lobo que la classe DefinitionFonction va traduire en C++

void DefinitionFonction::addCodeLobo(std::string lobo) {
	m_codeLobo.push_back(lobo);
}

// Fonction qui analyse le code Lobo donnée afin de le traduire en C++

void DefinitionFonction::analyser() {
	std::stringstream ss;
	for(int i = 0; i < m_codeLobo.size(); ++i){
		ss << m_codeLobo.at(i)+" ";
	}
	std::string s;
	getline(ss, s, ' ');
	if(s.compare("FONCTION")==0){
		getline(ss, s, ' ');
		m_identifiant = new Identifiant();
		m_identifiant->setParametre(s);

		getline(ss, s, ' ');
		if(s.compare("PARAMETRES")==0){
			getline(ss, s, ' ');
			while(s.compare("DEBUT")!=0){ // Ensemble des paramètres de la fonction
				m_identifiants.push_back(new Identifiant());
				m_identifiants.at(m_identifiants.size()-1)->setParametre(s);
				getline(ss, s, ' ');
			}
			while(s.compare("RETOUR")!=0){
				getline(ss, s, ' ');
				if(s.compare("REPETE")==0){//REPETE
					std::string str = "REPETE";
					int repeteImbrique = 0;
					while(s.compare("FIN_REPETE")!=0 || repeteImbrique!=0){
						if(s.compare("FIN_REPETE")==0){
							--repeteImbrique;
						}
						getline (ss, s, ' ');
						if(s.compare("REPETE")==0){
							++repeteImbrique;
						}

						str+=" "+s;
					}

					str+=" FIN_REPETE";

					m_instructionBases.push_back(new Repete());
					m_instructionBases.at(m_instructionBases.size()-1)->addCodeLobo(str);
					m_instructionBases.at(m_instructionBases.size()-1)->analyser();

				}else if(s.compare("APPEL")==0){ // APPEL FONCTION

					getline (ss, s, ';');
					std::string str = "APPEL "+s+";";

					m_instructionBases.push_back(new AppelFonction());
					m_instructionBases.at(m_instructionBases.size()-1)->addCodeLobo(str);
					m_instructionBases.at(m_instructionBases.size()-1)->analyser();

				}else if(s.compare("DECLARE")==0){ // DECLARE VARIABLE
					getline (ss, s, ';');
					std::string str = "DECLARE "+s+";";

					m_instructionBases.push_back(new DeclareVariable());
					m_instructionBases.at(m_instructionBases.size()-1)->addCodeLobo(str);
					m_instructionBases.at(m_instructionBases.size()-1)->analyser();

				}else if(s.compare("AFFECTE")==0){ // AFFECTE VARIABLE
					getline (ss, s, ';');
					std::string str = "AFFECTE "+s+";";

					m_instructionBases.push_back(new AffecteVariable());
					m_instructionBases.at(m_instructionBases.size()-1)->addCodeLobo(str);
					m_instructionBases.at(m_instructionBases.size()-1)->analyser();

				}else if(s.compare("AFFICHE")==0){ // AFFICHE CHAINE
					getline (ss, s, ';');
					std::string str = "AFFICHE "+s+";";

					m_instructionBases.push_back(new AfficheChaine());
					m_instructionBases.at(m_instructionBases.size()-1)->addCodeLobo(str);
					m_instructionBases.at(m_instructionBases.size()-1)->analyser();

				}
			}
			getline (ss, s, ';');
			m_expression = new Expression();
			m_expression->addCodeLobo(s);
			m_expression->analyser();
		}

	}
}

//Fonction qui va retourner la définition fonction sous forme de code C++

std::string DefinitionFonction::toString() const {

	std::string s;
	s+="int "+m_identifiant->toString()+"(";
	for(int i = 0 ; i < m_identifiants.size() ; ++i){
		s+=" int "+m_identifiants.at(i)->toString();
		if(i < m_identifiants.size()-1){
			s+=",";
		}
	}
	s+=") {\n";

	for(int i = 0 ; i < m_instructionBases.size() ; ++i){
		s+=m_instructionBases.at(i)->toString()+"\n";
	}

	s+="return "+m_expression->toString()+";\n";

	s+="}\n";
	return s;
}

